﻿using SharpDepend.Architecture.Windows;
using System;
using Xamarin.Forms;

namespace SharpDepend.XamarinForms.Architecture.Windows
{
    public class ZWindow<TApplication> : ContentPage
    {
        private NavigationPage mNavigator;
        private static int mWindowShowCount = 0;

        internal IWindowBase<TApplication> WindowsBase { get; set; }

        internal object Parameter { get; set; }

        internal IBaseWindowContent<TApplication> WindowContent { get; set; }

        internal bool IsClosed { get; private set; }

        public static event Action OnFirstWindowShow;

        public static event Action OnLastWindowHide;

        public ZWindow(NavigationPage navigator)
        {
            NavigationPage.SetHasNavigationBar(this, false);

            IsClosed = true;

            if (navigator == null)
            {
                throw new ArgumentNullException(nameof(navigator));
            }
            mNavigator = navigator;
        }

        internal void Show()
        {
            IsClosed = false;
            mNavigator.PushAsync(this);
        }

        protected override void OnAppearing()
        {
            IsClosed = false;

            base.OnAppearing();

            ++mWindowShowCount;
            if (mWindowShowCount == 1)
            {
                var call = OnFirstWindowShow;
                if (call != null)
                {
                    call();
                }
            }

            WindowContent.OnShown(Parameter);
        }

        protected override void OnDisappearing()
        {
            --mWindowShowCount;
            if (mWindowShowCount == 0)
            {
                var call = OnLastWindowHide;
                if (call != null)
                {
                    call();
                }
            }

            if (IsClosed)
            {
                return;
            }
            IsClosed = true;

            WindowsBase.Close();

            WindowContent.OnClose();
        }

        internal void Close()
        {
            if (IsClosed)
            {
                return;
            }
            IsClosed = true;
            mNavigator.PopAsync();
        }
    }

    public class BaseWindow<TWindowContent, TController, TApplication>
        : Grid, IWindowBase<TApplication>
        where TWindowContent : View, IWindowContent<TController, TApplication>
        where TController : class, IController<TApplication>
    {
        private View mContentView;
        private Label labelTitle;

        /// <summary>
        /// Get the parent window of this control.
        /// </summary>
        public ZWindow<TApplication> ParentWindow { get; private set; }

        public IBaseWindowContent<TApplication> WindowContent { get; private set; }

        public IBaseWindowContent<TApplication> Window
        {
            get { return WindowContent; }
        }

        public string Title
        {
            get { return ParentWindow.Title; }
            set
            {
                ParentWindow.Title = value;
            }
        }

        public BaseWindow(TApplication application, NavigationPage navigation)
        {
            WindowContent = Activator.CreateInstance<TWindowContent>();

            mContentView = (View)(object)WindowContent;

            CheckIWindowInstance();

            string title = WindowContent.Title;

            // Create window.
            ParentWindow = new ZWindow<TApplication>(navigation);
            ParentWindow.Title = title;
            ParentWindow.WindowsBase = this;

            StackLayout buttons = new StackLayout();
            buttons.Orientation = StackOrientation.Horizontal;

            Button backButton = new Button();
            //backButton.Image = XamarinFormsHelper.ResourceImage("Images/Icons/back.png");
            backButton.Text = "Back";
            backButton.Clicked += delegate
            {
                // Click back.
                navigation.SendBackButtonPressed();
            };
            buttons.Children.Add(backButton);

            // Title.
            labelTitle = new Label();
            labelTitle.Text = title;
            buttons.Children.Add(labelTitle);

            Grid grid = new Grid();
            grid.RowDefinitions.Add(new RowDefinition { Height = 60 });
            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(50, GridUnitType.Star) });
            grid.Children.Add(buttons);
            grid.Children.Add(mContentView);
            Grid.SetRow(mContentView, 1);

            // Add the "UserControl" to the window.
            ParentWindow.Content = grid;

            WindowContent.Initialize(application, this);
        }

        /// <summary>
        /// Show dialog if not already is showed.
        /// </summary>
        /// <param name="parameter">Optional extra parameter.</param>
        public void Show(object parameter)
        {
            if (!ParentWindow.IsFocused)
            {
                // Store parameter to reuse it if another window should add ower this.
                ParentWindow.Parameter = parameter;

                ParentWindow.WindowContent = WindowContent;

                // Update title again. It can be dynamically changed.
                string title = WindowContent.Title;
                ParentWindow.Title = title;
                labelTitle.Text = title;

                ParentWindow.Show();
            }
        }

        /// <summary>
        /// Check method.
        /// </summary>
        private void CheckIWindowInstance()
        {
            if (!(WindowContent is IBaseWindowContent<TApplication>))
            {
                throw new Exception("Windows is not a part of IWindowBase.");
            }
        }

        /// <summary>
        /// Close window.
        /// </summary>
        public void Close()
        {
            ParentWindow.Close();

            var call = OnClosing;
            if (call != null)
            {
                call();
            }
        }


        public bool IsOpen
        {
            get { return !ParentWindow.IsClosed; }
        }

        public event Action OnClosing;
    }
}
